/****************************************************************************************
 * @brief 串口的相关配置
 *
 * @file bsp_usart.h
 *
 * @remark bsp_usart.h 串口配置文件，接口函数声明
 * 		   bsp_usart.c 外部接口函数的实现
 * 		   bsp_usart_it.c 中断响应函数配置处
 * 		   syscalls.c GCC环境下重定向printf的重要配置文件。MDK下无所谓，但加上无伤大雅
 *
 * @param  baudRate	 2400
 * 					 4800
 * 					 9600			RS232/RS485/BY8301常用
 * 					 19200
 * 					 38400
 * 					 57600
 * 					 115200
 * 					 128000
 * 					 2304000
 * 					 2560000
 * 					 4608000
 *
 * @note 【使用前必须初始化对应的串口 Usartx_Init [1 - 5]。】
 * 		 【若要使用中断 需先初始化对应的中断 Usartx_NVIC_Init [1 - 5]】
 * 		 【若要重定向printf，需要在初始化串口前调用 Usart_Set_Printf_Stream
 * 		 来设置printf重定向的 流】
 * 		 【因为不同环境下的printf可能底层实现不同，因此会发送错误，如GCC，本例程提供GCC 与 MDK切换
 * 		  IS_MDK 设置为0则表示本环境为GCC，反之为MDK，其它环境未测试过。
 * 		  MDK使用GCC环境也能正常工作，但是在初始化后会发送一个换行，建议使用对应的环境配置。】
 * 		 【建议在所有初始化的最后调用初始化，因为可能其它模块的初始化导致串口发送意外的数据】
 * 		 【GCC环境下请将syscalls.c文件加入工程编译，否则报错。】
 *
 *
 *                                   										TOM
 *                              										时间：2023/11/17
****************************************************************************************/

#ifndef __BSP_USART_H
#define __BSP_USART_H

#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include "stdio.h"
/**
  * 串口宏定义，不同的串口挂载的总线和IO不一样，移植时需要修改这几个宏
  * 1-修改总线时钟的宏，uart1挂载到APB2总线，其他uart挂载到APB1总线
  * 2-修改GPIO的宏
  */

///使用的环境，因为不同环境下printf实现不同，因此区分【keil使用MDK，CLION通常配置为gcc-arm-none-eabi】
#define IS_MDK                0

/** printf重定义相关配置【确认以定义并初始化，未定义报错，未初始化会导致进入死循环卡死】 */
extern USART_TypeDef *DEBUG_printf_Usartx;
#define DEBUG_Printf_USART          DEBUG_USART1

/** ------------------------- 串口1-USART1 ------------------------- */
#define  DEBUG_USART1                    USART1                      //使用的USART1~5
#define  DEBUG_USART1_CLK                RCC_APB2Periph_USART1       //USART时钟RCC
#define  DEBUG_USART1_APBxClkCmd         RCC_APB2PeriphClockCmd      //USART时钟使能函数名
#define  DEBUG_USART1_BAUDRATE           115200                      //使用的波特率（通常使用 115200），RS232使用 9600
// USART1 GPIO 引脚宏定义
#define  DEBUG_USART1_GPIO_CLK           (RCC_APB2Periph_GPIOA)      //USART使用的GPIO时钟RCC
#define  DEBUG_USART1_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd      //GPIO时钟使能函数名
#define  DEBUG_USART1_TX_GPIO_PORT       GPIOA                       //发送位所使用的GPIO
#define  DEBUG_USART1_TX_GPIO_PIN        GPIO_Pin_9                  //发送位所使用的GPIO位
#define  DEBUG_USART1_RX_GPIO_PORT       GPIOA                       //接收位所使用的GPIO
#define  DEBUG_USART1_RX_GPIO_PIN        GPIO_Pin_10                 //接收位所使用的GPIO位
// USART1 中断配置
#define  DEBUG_USART1_IRQ                USART1_IRQn                 //串口所使用的中断
#define  DEBUG_USART1_IRQHandler         USART1_IRQHandler           //USART1串口中断服务函数
#define  DEBUG_USART1_IT_Preemption      1                           //抢占优先级
#define  DEBUG_USART1_IT_Sub             1                           //子优先级


/** ------------------------- 串口2-USART2 ------------------------- */
#define  DEBUG_USART2                    USART2                      //使用的USART1~5
#define  DEBUG_USART2_CLK                RCC_APB1Periph_USART2       //USART时钟RCC
#define  DEBUG_USART2_APBxClkCmd         RCC_APB1PeriphClockCmd      //USART时钟使能函数名
#define  DEBUG_USART2_BAUDRATE           115200                      //使用的时钟频率
// USART2 GPIO 引脚宏定义
#define  DEBUG_USART2_GPIO_CLK           (RCC_APB2Periph_GPIOA)      //USART使用的GPIO时钟RCC
#define  DEBUG_USART2_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd      //GPIO时钟使能函数名
#define  DEBUG_USART2_TX_GPIO_PORT       GPIOA                       //发送位所使用的GPIO
#define  DEBUG_USART2_TX_GPIO_PIN        GPIO_Pin_2                  //发送位所使用的GPIO位
#define  DEBUG_USART2_RX_GPIO_PORT       GPIOA                       //接收位所使用的GPIO
#define  DEBUG_USART2_RX_GPIO_PIN        GPIO_Pin_3                  //接收位所使用的GPIO位
#define  DEBUG_USART2_IRQ                USART2_IRQn                 //串口所使用的中断
// USART2 中断配置
#define  DEBUG_USART2_IRQHandler         USART2_IRQHandler           //USART2串口中断服务函数
#define  DEBUG_USART2_IT_Preemption      1                           //抢占优先级
#define  DEBUG_USART2_IT_Sub             2                           //子优先级


/** ------------------------- 串口3-USART3 ------------------------- */
#define  DEBUG_USART3                    USART3                      //使用的USART1~5
#define  DEBUG_USART3_CLK                RCC_APB1Periph_USART3       //USART时钟RCC
#define  DEBUG_USART3_APBxClkCmd         RCC_APB1PeriphClockCmd      //USART时钟使能函数名
#define  DEBUG_USART3_BAUDRATE           9600                      //使用的时钟频率
// USART3 GPIO 引脚宏定义
#define  DEBUG_USART3_GPIO_CLK           (RCC_APB2Periph_GPIOB)      //USART使用的GPIO时钟RCC
#define  DEBUG_USART3_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd      //GPIO时钟使能函数名
#define  DEBUG_USART3_TX_GPIO_PORT       GPIOB                       //发送位所使用的GPIO
#define  DEBUG_USART3_TX_GPIO_PIN        GPIO_Pin_10                 //发送位所使用的GPIO位
#define  DEBUG_USART3_RX_GPIO_PORT       GPIOB                       //接收位所使用的GPIO
#define  DEBUG_USART3_RX_GPIO_PIN        GPIO_Pin_11                 //接收位所使用的GPIO位
#define  DEBUG_USART3_IRQ                USART3_IRQn                 //串口所使用的中断
#define  DEBUG_USART3_IRQHandler         USART3_IRQHandler           //USART3串口中断服务函数
#define  DEBUG_USART3_IT_Preemption      2                           //抢占优先级
#define  DEBUG_USART3_IT_Sub             0                           //子优先级



/** ------------------------- 串口4-USART4 ------------------------- */
#define  DEBUG_USART4                    UART4                      //使用的USART1~5
#define  DEBUG_USART4_CLK                RCC_APB1Periph_UART4       //USART时钟RCC
#define  DEBUG_USART4_APBxClkCmd         RCC_APB1PeriphClockCmd      //USART时钟使能函数名
#define  DEBUG_USART4_BAUDRATE           115200                      //使用的时钟频率
// USART4 GPIO 引脚宏定义
#define  DEBUG_USART4_GPIO_CLK           (RCC_APB2Periph_GPIOC)      //USART使用的GPIO时钟RCC
#define  DEBUG_USART4_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd      //GPIO时钟使能函数名
#define  DEBUG_USART4_TX_GPIO_PORT       GPIOC                       //发送位所使用的GPIO
#define  DEBUG_USART4_TX_GPIO_PIN        GPIO_Pin_10                 //发送位所使用的GPIO位
#define  DEBUG_USART4_RX_GPIO_PORT       GPIOC                       //接收位所使用的GPIO
#define  DEBUG_USART4_RX_GPIO_PIN        GPIO_Pin_11                 //接收位所使用的GPIO位
#define  DEBUG_USART4_IRQ                UART4_IRQn                  //串口所使用的中断
#define  DEBUG_USART4_IRQHandler         UART4_IRQHandler           //USART4串口中断服务函数
#define  DEBUG_USART4_IT_Preemption      2                           //抢占优先级
#define  DEBUG_USART4_IT_Sub             1                           //子优先级


/** ------------------------- 串口5-UART5 ------------------------- */
#define  DEBUG_USART5                    UART5
#define  DEBUG_USART5_CLK                RCC_APB1Periph_UART5
#define  DEBUG_USART5_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART5_BAUDRATE           115200
// USART5 GPIO 引脚宏定义
#define  DEBUG_USART5_GPIO_CLK           (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD)     //RCC_APB2Periph_GPIOC输入GPIO，GPIOD为输出GPIO
#define  DEBUG_USART5_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd                          //输入输出GPIO时钟函数名
#define  DEBUG_USART5_TX_GPIO_PORT       GPIOC                                           //输出GPIO基地址
#define  DEBUG_USART5_TX_GPIO_PIN        GPIO_Pin_12                                     //输出位
#define  DEBUG_USART5_RX_GPIO_PORT       GPIOD                                           //输入GPIO基地址
#define  DEBUG_USART5_RX_GPIO_PIN        GPIO_Pin_2                                      //输入位
#define  DEBUG_USART5_IRQ                UART5_IRQn                                      //串口使用的中断配置
#define  DEBUG_USART5_IRQHandler         UART5_IRQHandler                                //USART5中断服务函数
#define  DEBUG_USART5_IT_Preemption      2                                               //抢占优先级
#define  DEBUG_USART5_IT_Sub             2                                               //子优先级


/** ----------------------------- 函数声明 ----------------------------- */
void Usart_Set_Printf_Stream(USART_TypeDef *Usartx);


void Usart1_Init(uint32_t baudRate);        //USART GPIO 配置,工作参数配置
void Usart1_SendByte(uint8_t data);
void Usart1_Send2Byte(const uint16_t data);
void Usart1_SendArray(const uint8_t *array, uint32_t len);
void Usart1_SendString(const uint8_t *str);
uint8_t Usart1_ReceiveByte(void);


void Usart2_Init(uint32_t baudRate);        //USART GPIO 配置,工作参数配置
void Usart2_SendByte(uint8_t data);
void Usart2_Send2Byte(const uint16_t data);
void Usart2_SendArray(const uint8_t *array, uint32_t len);
void Usart2_SendString(const uint8_t *str);
uint8_t Usart2_ReceiveByte(void);

void Usart3_Init(uint32_t baudRate);        //USART GPIO 配置,工作参数配置
void Usart3_SendByte(uint8_t data);
void Usart3_Send2Byte(const uint16_t data);
void Usart3_SendArray(const uint8_t *array, uint32_t len);
void Usart3_SendString(const uint8_t *str);
uint8_t Usart3_ReceiveByte(void);

void Usart4_Init(uint32_t baudRate);        //USART GPIO 配置,工作参数配置
void Usart4_SendByte(uint8_t data);
void Usart4_Send2Byte(const uint16_t data);
void Usart4_SendArray(const uint8_t *array, uint32_t len);
void Usart4_SendString(const uint8_t *str);
uint8_t Usart4_ReceiveByte(void);

void Usart5_Init(uint32_t baudRate);        //USART GPIO 配置,工作参数配置
void Usart5_SendByte(uint8_t data);
void Usart5_Send2Byte(const uint16_t data);
void Usart5_SendArray(const uint8_t *array, uint32_t len);
void Usart5_SendString(const uint8_t *str);
uint8_t Usart5_ReceiveByte(void);

void Usart1_NVIC_Init(uint8_t pre, uint8_t sub);
void Usart2_NVIC_Init(uint8_t pre, uint8_t sub);
void Usart3_NVIC_Init(uint8_t pre, uint8_t sub);
void Usart4_NVIC_Init(uint8_t pre, uint8_t sub);
void Usart5_NVIC_Init(uint8_t pre, uint8_t sub);

#endif

